﻿#include "frminput2019.h"
#include "ui_frminput2019.h"

#pragma execution_character_set("utf-8")
#define TIMEMS QTime::currentTime().toString("HH:mm:ss zzz")

frmInput2019 *frmInput2019::self = NULL;
frmInput2019 *frmInput2019::Instance()
{
    if (!self) {
        static QMutex mutex;
        QMutexLocker locker(&mutex);
        if (!self) {
            self = new frmInput2019;
        }
    }

    return self;
}

frmInput2019::frmInput2019(QWidget *parent) : QWidget(parent), ui(new Ui::frmInput2019)
{
    ui->setupUi(this);
    this->initForm();
    this->initServer();
    //QTimer::singleShot(10, this, SLOT(initServer()));
    QTimer::singleShot(100, this, SLOT(initData()));
}

frmInput2019::~frmInput2019()
{
    delete ui;
}

void frmInput2019::showEvent(QShowEvent *)
{
    //主动刷新下防止部分嵌入式板子刷新不及时导致残影
    this->update();

    //首次加载设置图标尺寸
    static bool isShow = false;
    if (!isShow) {
        isShow = true;
        this->initIconSize();
    }
}

bool frmInput2019::eventFilter(QObject *watched, QEvent *event)
{
    //qDebug() << TIMEMS << watched << event;
    if (watched == this) {
        //处理自身拖动
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
        //按下的时候记住坐标,移动到鼠标松开的位置
        if (event->type() == QEvent::MouseButtonPress) {
            if (mouseEvent->button() == Qt::LeftButton) {
                mousePressed = true;
                mousePoint = mouseEvent->globalPos() - this->pos();
                return true;
            }
        } else if (event->type() == QEvent::MouseButtonRelease) {
            mousePressed = false;
            return true;
        } else if (event->type() == QEvent::MouseMove) {
            //bottom为固定的底部禁用拖动
            if (mousePressed && position != "bottom") {
                this->move(mouseEvent->globalPos() - mousePoint);
                this->update();
                return true;
            }
        }
    } else if (watched == ui->labMore) {
        //打开更多汉字候选面板
        if (event->type() == QEvent::MouseButtonPress) {
            //中文模式+非大写+有汉字 才能打开,否则打开没有意义是空的
            if (inputType == "chinese" && !upper && pinyinHelper.getCount() > 0) {
                setWidgetVisible(ui->widgetChinese->isVisible() ? 1 : 3);
                //重新设置图标
                QString strMore = ui->widgetMore->isVisible() ? "up" : "down";
                ui->labMore->setPixmap(QString(":/image/btn_%1_%2.png").arg(strMore).arg(iconType));
                return true;
            } else {
                //在非（中文模式+非大写+有汉字）情况下点击关闭输入框
                ui->btnClose->click();
                return true;
            }
        }
    } else if (watched == ui->labType) {
        //中英模式切换,由于采用的标签所以在这里处理
        if (event->type() == QEvent::MouseButtonPress) {
            setInputType(inputType == "english" ? "chinese" : "english");
        }
    } else if (watched == ui->labType2) {
        //固定切换到英文模式
        if (event->type() == QEvent::MouseButtonPress) {
            setInputType("english");
        }
    } else if (watched == ui->widgetCn) {
        //没有汉字或者按下的地方没有汉字或者当前汉字标签个数过少都不用继续
        if (pinyinHelper.getCount() == 0 || lastText.isEmpty()) {
            return false;
        }

        //记住最后按下拖动的时间,过短则认为是滑动,启动滑动动画
        static bool pressed = false;
        static QPoint lastPos = QPoint();
        static QDateTime lastTime = QDateTime::currentDateTime();
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);

        if (event->type() == QEvent::MouseButtonPress) {
            pressed = true;
            lastPos = mouseEvent->pos();
            animationCn->stop();
            lastTime = QDateTime::currentDateTime();
        } else if (event->type() == QEvent::MouseButtonRelease) {
            pressed = false;
            if (lastPos != mouseEvent->pos()) {
                //判断当前时间和鼠标按下事件比较,时间短则说明是滑动
                QDateTime now = QDateTime::currentDateTime();
                if (lastTime.msecsTo(now) < 600) {
                    //可以改变下面的值来调整幅度
                    bool moveleft = (mouseEvent->pos().x() - lastPos.x()) < 0;
                    int offset = moveleft ? 350 : -350;
                    int value = ui->scrollAreaCn->horizontalScrollBar()->value();
                    animationCn->setStartValue(value);
                    animationCn->setEndValue(value + offset);
                    animationCn->start();
                }
            }
        } else if (event->type() == QEvent::MouseMove) {
            if (pinyinHelper.getCount() > 0 && pressed) {
                //计算滑过的距离,可以改变下面的值来调整幅度
                bool moveleft = (mouseEvent->pos().x() - lastPos.x()) < 0;
                int offset = moveleft ? 5 : -5;
                int value = ui->scrollAreaCn->horizontalScrollBar()->value();
                ui->scrollAreaCn->horizontalScrollBar()->setValue(value + offset);
                return true;
            }
        }
    } else if (watched == ui->widgetMore) {
        //没有汉字或者按下的地方没有汉字或者当前汉字标签个数过少都不用继续
        if (pinyinHelper.getCount() == 0 || lastText.isEmpty()) {
            return false;
        }

        //记住最后按下拖动的时间,过短则认为是滑动,启动滑动动画
        static bool pressed = false;
        static QPoint lastPos = QPoint();
        static QDateTime lastTime = QDateTime::currentDateTime();
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);

        if (event->type() == QEvent::MouseButtonPress) {
            pressed = true;
            lastPos = mouseEvent->pos();
            animationMore->stop();
            lastTime = QDateTime::currentDateTime();
        } else if (event->type() == QEvent::MouseButtonRelease) {
            pressed = false;
            if (lastPos != mouseEvent->pos()) {
                //判断当前时间和鼠标按下事件比较,时间短则说明是滑动
                QDateTime now = QDateTime::currentDateTime();
                if (lastTime.msecsTo(now) < 600) {
                    //可以改变下面的值来调整幅度
                    bool movebottom = (mouseEvent->pos().y() - lastPos.y()) < 0;
                    int offset = movebottom ? 150 : -150;
                    int value = ui->scrollAreaMore->verticalScrollBar()->value();
                    animationMore->setStartValue(value);
                    animationMore->setEndValue(value + offset);
                    animationMore->start();
                }
            }
        } else if (event->type() == QEvent::MouseMove) {
            if (pinyinHelper.getCount() > 0 && pressed) {
                //计算滑过的距离,可以改变下面的值来调整幅度
                bool movebottom = (mouseEvent->pos().y() - lastPos.y()) < 0;
                int offset = movebottom ? 5 : -5;
                int value = ui->scrollAreaMore->verticalScrollBar()->value();
                ui->scrollAreaMore->verticalScrollBar()->setValue(value + offset);
                return true;
            }
        }
    } else if (watched->inherits("QLabel")) {
        //单击的是汉字标签
        QLabel *lab = (QLabel *)watched;
        if (!upper && inputType == "chinese") {
            if (lab->property("labCn").toBool()) {
                //记住最后按下的滚动条位置,如果滚动条一直没有变化则认为单击了标签
                static int lastPosition = 0;
                if (event->type() == QEvent::MouseButtonPress) {
                    lastPosition = ui->scrollAreaCn->horizontalScrollBar()->value();
                    lastText = lab->text();
                } else if (event->type() == QEvent::MouseButtonRelease) {
                    if (lastPosition == ui->scrollAreaCn->horizontalScrollBar()->value() && !lastText.isEmpty()) {
                        insertValue(lab->text());
                        pinyinHelper.clearChinese();
                    }
                }
            } else if (lab->property("labMore").toBool()) {
                //记住最后按下的滚动条位置,如果滚动条一直没有变化则认为单击了标签
                static int lastPosition = 0;
                if (event->type() == QEvent::MouseButtonPress) {
                    lastPosition = ui->scrollAreaMore->verticalScrollBar()->value();
                    lastText = lab->text();
                } else if (event->type() == QEvent::MouseButtonRelease) {
                    if (lastPosition == ui->scrollAreaMore->verticalScrollBar()->value() && !lastText.isEmpty()) {
                        insertValue(lab->text());
                        pinyinHelper.clearChinese();
                    }
                }
            }
        }
    } else {
        if (event->type() == QEvent::MouseButtonPress) {
            //处理鼠标按下,如果是浏览器控件则弹出输入法
            if (currentWidget != 0) {
                if (!isVisible()) {
                    if (needInput()) {
                        showPanel();
                    }
                }
            } else {
                if (!isVisible()) {
                    //解决首次就有焦点的控件弹出输入法
                    currentWidget = (QWidget *)watched;
                    if (needInput()) {
                        showPanel();
                    }
                }
            }
        } else if (event->type() == QEvent::KeyPress) {
            //这里是实体键盘同步的代码 识别不同的按键映射到不同的按钮
            if (useHardKeyBoard) {
                bool doKey = true;
                QString labText = ui->labPinYin->text();
                QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
                if (keyEvent->key() == Qt::Key_Space) {
                    ui->btnSpace->click();
                } else if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
                    doKey = false;
                    if (!labText.isEmpty()) {
                        insertValue(labText);
                        pinyinHelper.clearChinese();
                        ui->labPinYin->clear();
                    } else {
                        //如果不需要回车隐藏则注释下面这句
                        hidePanel();
                    }
                } else if (keyEvent->key() == Qt::Key_Shift) {
                    //shift按键用来切换中英
                    sendEvent(0, "");
                } else if (keyEvent->key() == Qt::Key_Alt) {
                    //alt按键用来切换数字
                    ui->btnChar->isVisible() ? ui->btnChar->click() : ui->btnChar2->click();
                } else if (keyEvent->key() == Qt::Key_Escape) {
                    //关闭窗体
                    ui->btnClose->click();
                } else if (keyEvent->key() == Qt::Key_CapsLock) {
                    //大小写切换
                    ui->btnUpper->click();
                } else if (keyEvent->key() == Qt::Key_Backspace) {
                    doKey = false;
                    //中文模式下如果有输入字母则先挨个删除
                    if (inputType == "chinese") {
                        int len = labText.length();
                        if (len > 0) {
                            ui->labPinYin->setText(labText.left(len - 1));
                            pinyinHelper.selectChinese(ui->labPinYin->text());
                            doKey = true;
                        }
                    }
                } else if (keyEvent->text() == "+" || keyEvent->text() == "=") {
                    //汉字翻页 下一页
                    if (!labText.isEmpty()) {
                        pinyinHelper.showNext();
                    } else {
                        doKey = false;
                    }
                } else if (keyEvent->text() == "-" || keyEvent->text() == "_") {
                    //汉字翻页 上一页
                    if (!labText.isEmpty()) {
                        pinyinHelper.showPrevious();
                    } else {
                        doKey = false;
                    }
                } else {
                    doKey = false;
                    if (!isVisible()) {
                        return false;
                    }

                    QString key = keyEvent->text();
                    if (inputType == "english") {
                        //key = upper ? key.toUpper() : key.toLower();
                    }

                    //限定单个字母而不是输入的汉字
                    if (inputType == "chinese" && key.length() == 1) {
                        QList<QPushButton *> btns = ui->widgetLetter->findChildren<QPushButton *>();
                        foreach (QPushButton *btn, btns) {
                            QString text = btn->text();
                            if (!text.isEmpty() && text == key) {
                                btn->click();
                                doKey = true;
                                break;
                            }
                        }

                        //数字键选择汉字
                        if (useHardKeyBoard) {
                            int value = key.toInt();
                            if (value >= 1 && value <= maxCountCh) {
                                QString text = labCh.at(value - 1)->text();
                                if (!text.isEmpty()) {
                                    lastText = text;
                                    insertValue(text);
                                    pinyinHelper.clearChinese();
                                    ui->labPinYin->clear();
                                    doKey = true;
                                }
                            }
                        }
                    }
                }

                if (doKey) {
                    return true;
                }
            }
        } else if (event->type() == QEvent::RequestSoftwareInputPanel) {
            showPanel();
        } else if (event->type() == QEvent::CloseSoftwareInputPanel) {
            hidePanel();
        }
    }

    return QWidget::eventFilter(watched, event);
}

void frmInput2019::initForm()
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
    setWindowFlags(Qt::Tool | Qt::WindowDoesNotAcceptFocus | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
#else
    setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
#endif

    mousePoint = QPoint(0, 0);
    mousePressed = false;

    upper = false;
    charType = 0;

    onlyControl = false;
    onlyTouch = false;
    hideLabelNoText = true;
    useHardKeyBoard = false;

    currentWidget = 0;
    dbPath = qApp->applicationDirPath();

    //合法的输入控件,如果后面还发现其他控件也需要输入可以自行增加
    classNames << "QLineEdit" << "QTextEdit" << "QPlainTextEdit" << "QAbstractSpinBox" << "QComboBox";
    classNames << "QQuickWidget" << "QWebView" << "QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget";
}

bool frmInput2019::needInput()
{
    //查找当前焦点控件是否属于合法输入的控件
    bool exist = false;
    foreach (QString className, classNames) {
        if (currentWidget->inherits(className.toLatin1().constData())) {
            //如果当前是下拉框则判断下拉框可编辑属性是否为真
            //下面这个判断很巧妙哦,即能识别除了下拉框以外的控件还能识别可编辑的下拉框
            if (className != "QComboBox" || currentWidget->property("editable").toBool()) {
                exist = true;
                break;
            }
        }
    }
    return exist;
}

void frmInput2019::initServer()
{
    //初始化按钮和属性
    initBtn();
    //初始化显示汉字的标签
    initLab();
    //初始化动画属性用来滑动选择
    initAnimation();
    //初始化数字键盘
    initInputNumber();
    //初始化友元类
    initClass();

    //输入法面板的字体名称和按钮字体大小即汉字区域字体大小
    setFontInfo(this->font().family(), 11, 10);
    //面板固定大小
    setFixedSize2(650, 280);
    //图标固定大小
    setIconSize(20, 20);
    //按钮之间的间隔
    setSpacing(6);
    //顶部汉字区域高度
    setTopHeight(40);

    //输入法面板的显示位置  control--显示在对应输入框的正下方 bottom--填充显示在底部  center--窗体居中显示
    setPosition("control");
    //输入法模式 english--英文模式  chinese--中文模式  char--字符模式
    setInputType("english");
    //输入法面板的样式  black--黑色  blue--淡蓝色  brown--灰黑色  gray--灰色  silvery--银色
    setStyleName("black");
    //是否启用硬键盘
    setUseHardKeyBoard(false);
}

void frmInput2019::initBtn()
{
    //绑定按钮到事件
    QList<QPushButton *> btns;
    btns << ui->widgetLetter->findChildren<QPushButton *>();
    btns << ui->widgetChar->findChildren<QPushButton *>();
    foreach (QPushButton *btn, btns) {
        btn->setProperty("btnInput", true);
        connect(btn, SIGNAL(clicked()), this, SLOT(btnClicked()));
    }

    //设置字母属性
    btns.clear();
    btns << ui->widgetLetter1->findChildren<QPushButton *>();
    btns << ui->widgetLetter2->findChildren<QPushButton *>();
    foreach (QPushButton *btn, btns) {
        btn->setProperty("btnLetter", true);
    }

    //设置所有按钮输入法不可用+长按自动重复事件
    btns.clear();
    btns << this->findChildren<QPushButton *>();
    initBtn(btns);
}

void frmInput2019::initBtn(QList<QPushButton *> btns)
{
    foreach (QPushButton *btn, btns) {
        btn->setFocusPolicy(Qt::NoFocus);
        btn->setProperty("noinput", true);
        //如果不需要自动重复可以设置 setAutoRepeat(false)
        btn->setAutoRepeat(true);
        btn->setAutoRepeatDelay(500);
    }

    ui->btnClose->setHidden(true);
    ui->btnClose2->setHidden(true);
}

void frmInput2019::initLab()
{
    //实例化硬键盘使用的汉字标签
    maxCountCh = 5;
    for (int i = 0; i < maxCountCh; i++) {
        QLabel *lab = new QLabel;
        lab->setProperty("labCh", true);
        ui->layoutCh->addWidget(lab);
        labCh << lab;
    }

    //嵌入式板子性能低下可以限定最大数量
#ifdef __arm__
    maxCountCn = 100;
#else
    maxCountCn = 256;
#endif
    //实例化横向的汉字标签,添加到顶部滚动区域中
    for (int i = 0; i < maxCountCn; i++) {
        QLabel *lab = new QLabel;
        lab->setProperty("labCn", true);
        lab->setAlignment(Qt::AlignCenter);
        ui->layoutCn->addWidget(lab);
        labCn << lab;
    }

    //实例化更多的汉字标签,添加到更多滚动区域中
    int row = 0;
    int column = 0;
    //列数,可自行调整
    columnCount = 8;
    for (int i = 0; i < maxCountCn; i++) {
        QLabel *lab = new QLabel;
        lab->setProperty("labMore", true);
        lab->setAlignment(Qt::AlignCenter);
        ui->layoutMore->addWidget(lab, row, column);
        labMore << lab;

        column++;
        if (column >= columnCount) {
            row++;
            column = 0;
        }
    }

    //末尾加个弹簧
    //QSpacerItem *hSpacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
    //ui->layoutCn->addItem(hSpacer);
    QSpacerItem *vSpacer = new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding);
    ui->layoutMore->addItem(vSpacer, row + 1, 0);

    //lab1 lab2 空的占位置的标签  setEnabled(false)以后不会应用样式表
    ui->lab1->setEnabled(false);
    ui->lab2->setEnabled(false);
    ui->labPinYin->setEnabled(false);
    ui->labMore->setEnabled(false);
}

void frmInput2019::initAnimation()
{
    //定义动画产生平滑数值
    animationCn = new QPropertyAnimation(ui->scrollAreaCn->horizontalScrollBar(), "value");
    animationCn->setEasingCurve(QEasingCurve::OutCirc);
    animationCn->setDuration(500);

    animationMore = new QPropertyAnimation(ui->scrollAreaMore->verticalScrollBar(), "value");
    animationMore->setEasingCurve(QEasingCurve::OutCirc);
    animationMore->setDuration(500);
}

void frmInput2019::initInputNumber()
{
    QList<QPushButton *> btns;
    btns << ui->btnDelete << ui->btnSpace << ui->btnEnter << ui->btnClose;

    //char=共用一个面板切换到数字页面 number=独立的小数字面板
    numberType = "number";

    //数字键盘面板
    inputNumber = new frmInputNumber;
    this->layout()->addWidget(inputNumber);
    inputNumber->setInput(this);
    inputNumber->setBtns(btns);
    inputNumber->initClicked();
    inputNumber->hide();
}

void frmInput2019::initClass()
{
    //将部分功能独立出来放到其他类方便拓展和管理
    pinyinCustom.setInput(this);
    pinyinCustom.readChinese();

    QList<QPushButton *> btns = ui->widgetChar->findChildren<QPushButton *>();
    pinyinChar.setInput(this);
    pinyinChar.setBtns(btns);

    pinyinHelper.setInput(this);
    pinyinHelper.setLabs(labCh, labCn, labMore);
}

void frmInput2019::initData()
{
    if (onlyControl) {
        this->installEventFilter(this);
        ui->labType->installEventFilter(this);
        ui->labType2->installEventFilter(this);
        ui->labMore->installEventFilter(this);
        ui->widgetCn->installEventFilter(this);
        ui->widgetMore->installEventFilter(this);

        foreach (QLabel *lab, labCh) {
            lab->installEventFilter(this);
        }
        foreach (QLabel *lab, labCn) {
            lab->installEventFilter(this);
        }
        foreach (QLabel *lab, labMore) {
            lab->installEventFilter(this);
        }
    } else {
        //绑定全局改变焦点信号槽
        connect(qApp, SIGNAL(focusChanged(QWidget *, QWidget *)), this, SLOT(focusChanged(QWidget *, QWidget *)));
        qApp->installEventFilter(this);
    }

    pinyinGoogle.open(dbPath);
}

void frmInput2019::initIconSize()
{
    //图标尺寸大小
    QSize sizeUpper(iconWidth + 3, iconHeight);
    QSize sizeDelete(iconWidth + 10, iconHeight);
    QSize sizeEnter(iconWidth + 3, iconHeight);
    QSize sizeClose(iconWidth + 5, iconHeight + 3);

    ui->btnUpper->setIconSize(sizeUpper);
    ui->btnDelete->setIconSize(sizeDelete);
    ui->btnDelete2->setIconSize(sizeDelete);
    ui->btnEnter->setIconSize(sizeEnter);
    ui->btnEnter2->setIconSize(sizeEnter);
    ui->btnClose->setIconSize(sizeClose);
    ui->btnClose2->setIconSize(sizeClose);
}

void frmInput2019::btnClicked()
{
    clearScroll();
    QPushButton *btn = (QPushButton *)sender();
    QString objectName = btn->objectName();
    QString btnText = btn->text();
    QString labText = ui->labPinYin->text();

    //下面采用startsWith的判断是因为有多个按钮功能一样比如 btnDelete btnDelete2
    if (objectName == "btnUpper") {
        upper = !upper;
        setUpper(upper);
        pinyinHelper.clearChinese();
        ui->labPinYin->clear();
    } else if (objectName == "btnChar") {
        setInputType("char");
        //立即切换到初始的字符界面 注释掉的话则保留以前的最后字符状态
        pinyinChar.setCharType(0, ui->btnChar2);
    } else if (objectName == "btnChar2") {
        if (charType == 0) {
            charType = 1;
        } else if (charType == 1) {
            charType = 2;
        } else {
            charType = 0;
        }

        pinyinChar.setCharType(charType, ui->btnChar2);
    } else if (objectName.startsWith("btnDelete")) {
        //如果当前是中文模式,则删除对应拼音,删除完拼音之后再删除对应文本输入框的内容
        int len = labText.length();
        if (inputType == "chinese" && len > 0) {
            ui->labPinYin->setText(labText.left(len - 1));
            pinyinHelper.selectChinese(ui->labPinYin->text());
        } else {
            deleteValue();
        }
    } else if (objectName.startsWith("btnSpace")) {
        //如果中文模式而且有待输入字母,判断是否有中文则插入第一个中文否则插入字母
        if (inputType == "chinese" && !labText.isEmpty()) {
            QString text = useHardKeyBoard ? labCh.first()->text() : labCn.first()->text();
            text.isEmpty() ? insertValue(labText) : insertValue(text);
            pinyinHelper.clearChinese();
        } else {
            insertValue(" ");
        }
    } else if (objectName.startsWith("btnEnter")) {
        //如果中文模式而且有待输入字母则立即插入字母
        if (inputType == "chinese" && !labText.isEmpty()) {
            insertValue(labText);
            pinyinHelper.clearChinese();
        }

        qDebug() << (!onlyControl) << "~~~~~~~~~~zzzzzzzzzzzzzzzzzzzzzz";

        if (currentWidget != 0 && !onlyControl) {
            //如果手动指定了属性隐藏,或者不是多行文本则自动隐藏
            //如果单行文本不希望回车隐藏则设置属性 ui->txt->setProperty("enterhide", false);
            QVariant enterHide = currentWidget->property("enterhide");
            bool needHide = false;
            if (enterHide.isValid()) {
                if (enterHide.toBool()) {
                    needHide = true;
                }
            } else {
                if (!currentWidget->inherits("QTextEdit") && !currentWidget->inherits("QPlainTextEdit") && !currentWidget->inherits("QTextBrowser")) {
                    needHide = true;
                }
            }

            QWidget * tempCurrentWidget = currentWidget;
            if (needHide) {
                // 点击关闭输入法按钮使当前控件失去焦点
                if (currentWidget != 0) {
                    currentWidget->clearFocus();
                    this->currentWidget = 0;
                }
                hidePanel(false);
            }
//            //插入回车符
//            sendEvent(3, "");
            //插入回车符
            QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier, QString("\n"));
            QApplication::sendEvent(tempCurrentWidget, &keyPress);
        } else {
            insertValue("\n");
        }
    } else if (objectName.startsWith("btnClose")) {
        // 点击关闭输入法按钮使当前控件失去焦点
        if (currentWidget != 0) {
            currentWidget->clearFocus();
            this->currentWidget = 0;
        }
        hidePanel(false);
    } else {
        //如果是&按钮，因为对应&被过滤,所以真实的text为去除前面一个&字符
        if (btnText == "&&") {
            btnText = "&";
        }

        //当前不是中文模式,则单击按钮对应text为传递参数,大写优先
        //中文模式+非大写+并且按下的是字母按钮 则设置字母并查询汉字
        if (inputType != "chinese" || upper) {
            insertValue(btnText);
        } else {
            if (btn->property("btnLetter").toBool()) {
                ui->labPinYin->setText(labText + btnText);
                pinyinHelper.selectChinese(ui->labPinYin->text());
            }
        }
    }
}

//用来全局焦点切换的时候 处理输入法显示隐藏及模式切换和位置处理
void frmInput2019::focusChanged(QWidget *oldWidget, QWidget *nowWidget)
{
    //qDebug() << TIMEMS << "oldWidget:" << oldWidget << "nowWidget:" << nowWidget;
    this->currentWidget = nowWidget;
    //新焦点控件=0需要隐藏
        if (nowWidget == 0) {
            hidePanel();
            return;
        }

        if (nowWidget != 0 && !this->isAncestorOf(nowWidget)) {
            //如果对应属性noinput为真或者只读则不显示
            if (nowWidget->property("noinput").toBool() || nowWidget->property("readOnly").toBool()) {
                QTimer::singleShot(1, this, SLOT(hidePanel()));
                return;
            }

            if (nowWidget->inherits("QWidget")) {
                //需要输入法的地方弹出输入法否则隐藏
                if (needInput()) {
                    showPanel();
                } else {
                    //暂时关闭点击空白处关闭输入法功能
                    hidePanel();
                }
            }
        }
}

void frmInput2019::insertValue(const QString &value)
{
    //先过滤前面的标号
    QString text = value;
    if (text != " ") {
        text = value.split(" ").last();
    }

    //仅仅当做独立的面板使用,发送选择的内容即可
    if (onlyControl) {
        pinyinCustom.saveChinese(text.trimmed(), ui->labPinYin->text());
        clearValue();
        emit receiveValue(text);
        return;
    }

    if (currentWidget == 0) {
        return;
    }

    //保存当前选中汉字到文件,作为优先显示的汉字
    pinyinCustom.saveChinese(text.trimmed(), ui->labPinYin->text());

    //如果某个控件开启了永远大写则强制转换为大写
    bool upper = currentWidget->property("upper").toBool();
    text = upper ? text.toUpper() : text;
    if (!text.isEmpty()) {
        sendEvent(4, text);
    }

    clearValue();
}

void frmInput2019::clearValue()
{
    //清空拼音标签,同时滚动条恢复
    clearScroll();
    ui->labPinYin->clear();

    //如果是汉字面板显示则隐藏汉字面板并显示字母面板
    if (ui->widgetChinese->isVisible()) {
        setWidgetVisible(1);
        //重新设置图标
        QString strMore = ui->widgetMore->isVisible() ? "up" : "down";
        ui->labMore->setPixmap(QString(":/image/btn_%1_%2.png").arg(strMore).arg(iconType));
    }
}

void frmInput2019::deleteValue()
{
    if (currentWidget == 0) {
        return;
    }

    sendEvent(2, "");
}

void frmInput2019::clearScroll()
{
    ui->scrollAreaCn->horizontalScrollBar()->setValue(0);
    ui->scrollAreaMore->verticalScrollBar()->setValue(0);
}

void frmInput2019::showPanel()
{
    if (!isEnabled() || currentWidget == 0) {
        return;
    }

    //根据不同的标识符切换到不同的面板
    QString flag = currentWidget->property("flag").toString();
    if (currentWidget->inherits("QAbstractSpinBox")) {
        flag = "number";
    }

    //如果是父控件中的子控件需要过滤,比如表格控件自动出现的文本框,需要判断是否设置了number
    if (flag != "number") {
        QWidget *father = (QWidget *)currentWidget->parent();
        if (father != 0) {
            father = (QWidget *)father->parent();
            if (father != 0) {
                flag = father->property("flag").toString();
            }
        }
    }

    if (flag == "number") {
        if (inputType != numberType) {
            this->setVisible(false);
            setInputType(numberType);
        }
        pinyinChar.setCharType(0, ui->btnChar2);
    } else {
        if (inputType == numberType) {
            this->setVisible(false);
            setInputType("english");
        }
    }

    //先移动到对应的位置再显示输入法面板
    pinyinHelper.movePosition();
    this->setVisible(true);
}

void frmInput2019::hidePanel(bool clear)
{
    if (clear) {
        currentWidget = 0;
    }

    //如果已经是隐藏状态则不需要处理
    if (!isVisible()) {
        return;
    }

    //解决当更多汉字面板打开时候突然隐藏不会自动关闭的BUG
    if (ui->widgetMore->isVisible()) {
        sendEvent(1, "");
    }

    pinyinHelper.clearChinese();
    ui->labPinYin->clear();
    this->setVisible(false);
}

void frmInput2019::setWidgetVisible(int indexVisible)
{
    //显示候选汉字面板框需要设置标签的最小高度否则出现拥挤的情况
    //这里后面还要考虑是否限制只需要设置一次 各种环境多测试各种情况是否设置一次就永远生效
    if (!ui->widgetChinese->isVisible() && indexVisible == 3) {
        //先显示再隐藏防止闪烁
        ui->widgetChinese->setVisible(true);
        ui->widgetChinese->setVisible(false);
        int labFontSize = ui->labPinYin->font().pointSize();
        foreach (QLabel *lab, labMore) {
            lab->setFixedHeight(labFontSize + 30);
        }
    }

    ui->widgetLetter->setVisible(indexVisible == 1);
    ui->widgetChar->setVisible(indexVisible == 2);
    ui->widgetChinese->setVisible(indexVisible == 3);
    ui->widgetTop->setVisible(indexVisible != 4);
    inputNumber->setVisible(indexVisible == 4);

    //底部填充显示
    if (position == "bottom") {
        return;
    }

    //切换小数字键盘和全键盘
    if (indexVisible == 4) {
//        this->setFixedSize(fixedWidth / 2.2, fixedHeight / 1.2);
        // 暂时去掉中文
        this->setFixedSize(fixedWidth / 2.2, fixedHeight);
    } else {
        this->setFixedSize(fixedWidth / 1, fixedHeight / 1);
    }
}

void frmInput2019::sendEvent(quint8 type, const QString &text)
{
    if (type == 0) {
        //切换中英模式
        QMouseEvent mousePress(QEvent::MouseButtonPress, QPoint(0, 0), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
        QApplication::sendEvent(ui->labType->isVisible() ? ui->labType : ui->labType2, &mousePress);
    } else if (type == 1) {
        //隐藏汉字候选面板
        QMouseEvent mousePress(QEvent::MouseButtonPress, QPoint(0, 0), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
        QApplication::sendEvent(ui->labMore, &mousePress);
    } else if (type == 2) {
        //删除
        QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier, QString());
        QApplication::sendEvent(currentWidget, &keyPress);
    } else if (type == 3) {
        //插入回车符
        QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier, QString("\n"));
        QApplication::sendEvent(currentWidget, &keyPress);
    } else if (type == 4) {
        //插入字符
        QKeyEvent keyPress(QEvent::KeyPress, 0, Qt::NoModifier, QString(text));
        QApplication::sendEvent(currentWidget, &keyPress);
    }
}

void frmInput2019::setFontInfo(const QString &fontName, int btnFontSize, int labFontSize)
{
    QFont btnFont(fontName, btnFontSize);
    QFont labFont(fontName, labFontSize);

    QList<QPushButton *> btns = this->findChildren<QPushButton *>();
    foreach (QPushButton *btn, btns) {
        btn->setFont(btnFont);
    }

    //设置输入法类型标签字体
    ui->labType->setFont(btnFont);
    ui->labType2->setFont(btnFont);
    ui->labPinYin->setFont(labFont);

    //设置硬键盘使用的汉字标签
    foreach (QLabel *lab, labCh) {
        lab->setFont(labFont);
    }

    //设置横向滚动条中的汉字标签字体
    foreach (QLabel *lab, labCn) {
        lab->setFont(labFont);
    }

    //设置汉字候选面板中的汉字标签字体+高度
    foreach (QLabel *lab, labMore) {
        lab->setFont(labFont);
    }
}

void frmInput2019::setFixedSize2(int fixedWidth, int fixedHeight)
{
    this->fixedWidth = fixedWidth;
    this->fixedHeight = fixedHeight;
    this->setFixedSize(fixedWidth, fixedHeight);
}

void frmInput2019::setIconSize(int iconWidth, int iconHeight)
{
    this->iconWidth = iconWidth;
    this->iconHeight = iconHeight;
}

void frmInput2019::setSpacing(int spacing)
{
    ui->widgetLetter1->layout()->setSpacing(spacing);
    ui->widgetLetter2->layout()->setSpacing(spacing);
    ui->widgetLetter3->layout()->setSpacing(spacing);
    ui->widgetChar1->layout()->setSpacing(spacing);
    ui->widgetChar2->layout()->setSpacing(spacing);
    ui->widgetChar3->layout()->setSpacing(spacing);
    inputNumber->setSpacing(spacing);
}

void frmInput2019::setTopHeight(int topHeight)
{
    ui->widgetTop->setFixedHeight(topHeight);
}

void frmInput2019::setOnlyControl(bool onlyControl)
{
    this->onlyControl = onlyControl;
}

void frmInput2019::setOnlyTouch(bool onlyTouch)
{
    this->onlyTouch = onlyTouch;
    this->setStyleName(styleName);
}

void frmInput2019::setHideLabelNoText(bool hideLabelNoText)
{
    //默认是自动隐藏已经执行过,如果重新改动了则需要重新设置所有标签
    if (this->hideLabelNoText != hideLabelNoText) {
        this->hideLabelNoText = hideLabelNoText;
        if (!useHardKeyBoard) {
            for (int i = 0; i < maxCountCn; i++) {
                labCn.at(i)->setVisible(!hideLabelNoText);
                labMore.at(i)->setVisible(!hideLabelNoText);
            }
        }
    }
}

void frmInput2019::setUseHardKeyBoard(bool useHardKeyBoard)
{
    this->useHardKeyBoard = useHardKeyBoard;
    ui->widgetCh->setVisible(useHardKeyBoard);
    ui->scrollAreaCn->setVisible(!useHardKeyBoard);
    ui->labMore->setVisible(!useHardKeyBoard);
}

void frmInput2019::setColumnCount(int columnCount)
{
    this->columnCount = columnCount;
}

void frmInput2019::setMaxCount(int maxCountCn)
{
    this->maxCountCn = maxCountCn;
}

void frmInput2019::setNumberType(const QString &numberType)
{
    this->numberType = numberType;
}

void frmInput2019::setDbPath(const QString &dbPath)
{
    this->dbPath = dbPath;
}

void frmInput2019::setPosition(const QString &position)
{
    this->position = position;
}

void frmInput2019::setInputType(const QString &inputType)
{
    //每次模式更改都把原有的汉字清空
    clearScroll();
    pinyinHelper.clearChinese();
    ui->labPinYin->clear();

    //2021-9-17 修复切换字符按钮窗体会不自觉移动的BUG
    mousePressed = false;

    this->inputType = inputType;
    if (inputType == "number") {
        setWidgetVisible(4);
    } else if (inputType == "char") {
        setWidgetVisible(2);
    } else if (inputType == "english") {
        setWidgetVisible(1);
        //通过html设置文字产生不同汉字不同的颜色
        ui->labType->setText(QString("<font color='%1'>中/</font><font color='%2' size='4'>英</font>").arg(mainTextColor).arg(btnHoveColor));
    } else if (inputType == "chinese") {
        setWidgetVisible(1);
        //通过html设置文字产生不同汉字不同的颜色
        ui->labType->setText(QString("<font color='%2' size='4'>中</font><font color='%1'>/英</font>").arg(mainTextColor).arg(btnHoveColor));
    }

    //重新设置图标
    QString strMore = ui->widgetMore->isVisible() ? "up" : "down";
    ui->labMore->setPixmap(QString(":/image/btn_%1_%2.png").arg(strMore).arg(iconType));
}

void frmInput2019::setUpper(bool isUpper)
{
    QList<QPushButton *> btns = ui->widgetLetter->findChildren<QPushButton *>();
    foreach (QPushButton *btn, btns) {
        QString text = isUpper ? btn->text().toUpper() : btn->text().toLower();
        btn->setText(text);
    }

    //改变图标
    QString strUpper = upper ? "upper" : "lower";
    ui->btnUpper->setIcon(QIcon(QString(":/image/btn_%1_%2.png").arg(strUpper).arg(iconType)));
}

void frmInput2019::setStyleName(const QString &styleName)
{
    this->styleName = styleName;
    this->iconType = "white";
    if (styleName == "black") {
        setColor("#191919", "#F3F3F3", "#313131", "#24B1DF", "#F3F3F3", "#F95717", "#F3F3F3");
    } else if (styleName == "blue") {
        setColor("#377FC9", "#F3F3F3", "#4189D3", "#386487", "#F3F3F3", "#386487", "#F3F3F3");
    } else if (styleName == "gray") {
        setColor("#989898", "#FFFFFF", "#A2A2A2", "#333333", "#F3F3F3", "#2E2E2E", "#F3F3F3");
    } else if (styleName == "brown") {
        setColor("#667481", "#F3F3F3", "#566373", "#4189D3", "#F3F3F3", "#4189D3", "#F3F3F3");
    } else if (styleName == "silvery") {
        setColor("#868690", "#000002", "#C3C2C7", "#F0F0F0", "#000002", "#F0F0F0", "#000002");
        this->iconType = "black";
    }

    QString strMore = ui->widgetMore->isVisible() ? "up" : "down";
    QString strUpper = upper ? "upper" : "lower";
    ui->labMore->setPixmap(QString(":/image/btn_%1_%2.png").arg(strMore).arg(iconType));
    ui->btnUpper->setIcon(QIcon(QString(":/image/btn_%1_%2.png").arg(strUpper).arg(iconType)));

    QString strDelete = QString(":/image/btn_%1_%2.png").arg("delete").arg(iconType);
    QString strEnter = QString(":/image/btn_%1_%2.png").arg("enter").arg(iconType);
    QString strClose = QString(":/image/btn_%1_%2.png").arg("close").arg(iconType);
    ui->btnDelete->setIcon(QIcon(strDelete));
    ui->btnDelete2->setIcon(QIcon(strDelete));
    ui->btnEnter->setIcon(QIcon(strEnter));
    ui->btnEnter2->setIcon(QIcon(strEnter));
    ui->btnClose->setIcon(QIcon(strClose));
    ui->btnClose2->setIcon(QIcon(strClose));
}

void frmInput2019::setColor(const QString &mainBackgroundColor, const QString &mainTextColor,
                            const QString &btnBackgroundColor, const QString &btnHoveColor,
                            const QString &btnHoveTextColor, const QString &labHoveColor,
                            const QString &labHoveTextColor)
{
    this->mainTextColor = mainTextColor;
    this->btnHoveColor = btnHoveColor;

    QStringList list;
    list << QString("QScrollArea{border:none;background:rgba(255,255,255,0);}QWidget#widgetCn,QWidget#widgetMore{background:rgba(0,0,0,0);}");
    list << QString("QWidget#widgetTop,QWidget#widgetLetter,QWidget#widgetChar{background-color:%1;}").arg(mainBackgroundColor);
    list << QString("QWidget#widgetChinese,QWidget#widgetNumber{background-color:%1;}").arg(mainBackgroundColor);
    list << QString("#labType,#labType2,QPushButton{border-width:0px;border-radius:3px;color:%1;}").arg(mainTextColor);
    list << QString("#labType,#labType2,QPushButton{padding:0px;background-color:%1;}").arg(btnBackgroundColor);

    //触摸屏上不需要设置hover
    if (onlyTouch) {
        list << QString("QPushButton:pressed{background-color:%1;color:%2;}").arg(btnHoveColor).arg(btnHoveTextColor);
        list << QString("QLabel:pressed{background-color:%1;color:%2;}").arg(labHoveColor).arg(labHoveTextColor);
    } else {
        list << QString("QPushButton:pressed,QPushButton:hover{background-color:%1;color:%2;}").arg(btnHoveColor).arg(btnHoveTextColor);
        list << QString("QLabel:pressed,QLabel:hover{background-color:%1;color:%2;}").arg(labHoveColor).arg(labHoveTextColor);
    }

    list << QString("QLabel{padding:0px 5px 0px 5px;border-width:0px;border-radius:3px;color:%1;background:none;}").arg(mainTextColor);
    list << QString("QLabel:disabled{background:none;}");

    QString qss = list.join("");
    this->setStyleSheet(qss);

    ui->labType->setText(QString("<font color='%1'>中/</font><font color='%2' size='4'>英</font>").arg(mainTextColor).arg(btnHoveColor));
//    ui->labType2->setText(QString("<font color='%2' size='4'>中</font><font color='%1'>/英</font>").arg(mainTextColor).arg(btnHoveColor));
    // 暂时去除中文
    ui->labType2->setText(QString("<font color='%1' size='4'>En</font>").arg(btnHoveColor));
    qApp->processEvents();
}

void frmInput2019::hideAndClearFocus()
{
    //todo 可能有异常
    if (!isVisible()) {
        return;
    }
    if (currentWidget != 0) {
        currentWidget->clearFocus();
        currentWidget = 0;
    }
    hidePanel(false);
}

void frmInput2019::retranslateUiSlot()
{
    ui->retranslateUi(this);
    if (inputNumber)
    {
        inputNumber->retranslateUiSlot();
    }
}
